/*HTTP Server with GET request response
by Jason Curtis
2 Jun 2011

responds to http requests with a list of analog port values.
meanwhile, copies those http requests to SPI.
also provides functionality to act upon GET requests.

notable things: 
parseLine(String* line)
  parses an HTTP GET request line for arguments.
  it then calls keyValueAct(String key, String val) to act accordingly.
*/

#include <SPI.h>
#include <Client.h>
#include <Ethernet.h>
#include <Server.h>
#include <Udp.h>
#include <WString.h>


//MAC address from back of shield:
byte mac[] = {0x90,0xA2,0xDA,0x00,0x37,0x61};
//IP address (dynamic not supported I guess?)
byte ip[] = {192, 168, 1, 200};
//HTTP server to listen to client requests:
Server HServer(80);

//strings for storing & parsing GET key/val pairs
String readString = "";
String key = "";
String val = "";
int keyStart;
int keyEnd;
int valEnd;
int urlEnd;

void setup(){
  Ethernet.begin(mac, ip);  
  Serial.begin(9600);
  HServer.begin();
}


int keyValueAct(String key, String val){
  Serial.println("key: " + key + " value: " + val);
  //this is where you put what should take place
  //for different key/value pairs from web requests.
  
  if (key =="setpoint"){//for example
    //something like "setpoint = (int)val;"
    //or "setTemp(val);"
    
    //for now, let's just lie to the user:
    Serial.println("New Setpoint Is " + val);
  }
}


int parseLine(String* line){
  //parses an HTTP GET request line for arguments.
  //maybe works for POST too? untested.
  
  //end of URL is followed by a space
  urlEnd = line->lastIndexOf(" ");
  
  //GET vars, if there are any, are preceded by "?"
  keyStart = line->indexOf("?");
  if (keyStart != -1){
    while(keyStart != -1){
      
      //key name is usually followed by an equals sign
      keyEnd = line->indexOf("=", keyStart);
      if(keyEnd == -1){ //no equals sign
        if(urlEnd == keyStart+1){
          //there are no (more) keys
          break;
        }
        else{
          keyEnd = urlEnd;
        }
      }
      
      key = line->substring(keyStart + 1, keyEnd);
      Serial.println("key: " + key);
      
      //key values are followed by "&" or " ":
      valEnd = -1;
      valEnd = line->indexOf("&",keyEnd);
      if(valEnd == -1){
        valEnd = urlEnd;
      }
      if (keyEnd != valEnd){
        val = line->substring(keyEnd + 1, valEnd);
        Serial.println(" value: " + val);
      }
      else{
        Serial.println(" (no value)");
      }

      keyValueAct(key, val);
      
      //look for the next variable
      keyStart = line->indexOf("&",valEnd);
    }
  }
}


int doHttpPage(Client client){
  // prints an HTTP-formatted page for a client, with some info.
  
  // send a standard http response header
  client.println("HTTP/1.1 200 OK");
  client.println("Content-Type: text/html");
  client.println();

  // output the value of each analog input pin
  for (int analogChannel = 0; analogChannel < 6; analogChannel++) {
    client.print("analog input ");
    client.print(analogChannel);
    client.print(" is ");
    client.print(analogRead(analogChannel));
    client.println("<br />");
  }
  client.print("ms so far:");
  client.print(millis());
  client.println("<br/>");
  
  // give the web browser time to receive the data
  delay(1);
}

void loop(){
  // listen for incoming clients
  Client client = HServer.available();
  if (client) {
    while (client.connected()) {
      if (client.available()) { //there's something ready to read
        
        //read char by char HTTP request into buffer
        char c = client.read();
        readString += c;
        
        if (c == '\n') { //HTTP line has ended. time to parse.
          Serial.print("HTTP: ");
          Serial.print(readString);
          
          if (readString.startsWith("GET")){
            //parse GET arguments and act upon them.
            parseLine(&readString);
          }
          
          //clear string for next line
          readString="";
        }
        
        if (!client.available()){
          //we have read all there is to read

          //reply
          doHttpPage(client); 
          //close connection
          client.stop();
        }
      }
    }
  }
}

